package com.vivek.guess.what.calculator;

import static com.vivz.guess.what.util.GuessWhatUtil.getDifferenceAgainstSet;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.vivz.guess.what.type.Position;
import com.vivz.guess.what.vo.Clue;
import com.vivz.guess.what.vo.Guess;
import com.vivz.guess.what.vo.ProbabilityMatrix;

/**
 * <pre>
 * 2. Check for the definite insiders with their definite positions
 * 
 * Check all the guessed words' weights that match the regex : [x]+ against the zero weights.
 * 
 * Use case #1: you have Xs = valid diff betn 0-weight word and guess-word
 * KING ----
 * WIND XX
 * .IN. intersection
 * W..D valid diff (Here you know for sure that W & D are definitely at 1st and 4th postions)
 * 
 * Use case #2: you have Xs < diff betn 0-weight word and guess-word
 * KING ----
 * WILD XX
 * .I.. intersection
 * W.LD valid diff (Here you know that 2 of W, L & D are definitely at their right places and CANNOT be anywhere else)
 * 
 * Use case #3: you have Xs > diff betn 0-weight word and guess-word [NOT POSSIBLE]
 * (Possible when the opponent is a human and has probably given a wrong weighted clue)
 * KING ----
 * RING XX
 * .IN. intersection
 * R... valid diff (Here you know for sure that there was a wrong clue entered)
 * 
 * 
 * Rough text:
 * 
 * In prob map the chars with more than one position probabilities make to the possible insiders group,
 * the ones with only one position make to the definite insiders (however there is one sitiuation use case#2 where this could be wrong)
 * </pre>
 */
public class ZeroPlusXCalculator extends AbstractCalculator {

	@Override
	public void calculate(final List<Guess> guesses, final ProbabilityMatrix pMatrix) {
		for (final Guess g : guesses) { // ..................... compare a guess
			final Clue clue = g.getClue();
			if (clue.hasCrossesOnly()) { // ..... with a [x]+ clue
				final Map<Character, Position> difference = getDifferenceAgainstSet(g, pMatrix.getDefiniteOutsiders());

				if (difference.isEmpty()) {
					// This is one of the possibilities in the Use case #3 - boo hoo
				} else {
					final int diff = difference.size();
					final int countX = clue.getCountX();
					final boolean confirmed = diff == countX;

					if (diff >= countX) {
						// This is the Use case #1
						for (final Entry<Character, Position> entry : difference.entrySet()) {
							final Character c = entry.getKey();
							final Position p = entry.getValue();
							p.setConfirmed(confirmed);
							pMatrix.markOnlyPossiblePosition(c, p);
						}

					} else {
						// This is one of the possibilities in the Use case #3 - boo hoo
					}
				}
			}
		}
	}

}
